<template>
  <template
    v-for="{ formValueProps, colProps, slots: formItemSlots, ...item } in columns"
    :key="item.prop"
  >
    <ColWrapper :grid="grid" v-bind="grid ? colProps : {}">
      <component :is="isQueryFormItem ? QueryFormItem : ElFormItem" :prop="item.prop" v-bind="item">
        <!-- 处理 el-form-item的插槽 中的插槽配置 -->
        <template
          v-for="(slotValue, slotName) in formItemSlots"
          :key="slotName"
          #[slotName]="slotData"
        >
          <template v-if="typeof slotValue === 'function'">
            <!-- 如果是渲染函数，直接执行 -->
            <component :is="slotValue(slotData)" />
          </template>
          <template v-else-if="typeof slotValue === 'string'">
            <!-- 如果是字符串，表示插槽名，从父组件插槽中获取 -->
            <slot :name="slotValue" v-bind="slotData" />
          </template>
        </template>

        <!-- 表单内容组件     -->
        <FormValue v-model="value[item.prop]" :column="formValueProps">
          <template v-for="(_, name) in valueSlots" #[name]="slotData" :key="name">
            <slot :name="name" v-bind="slotData" />
          </template>
        </FormValue>
      </component>
    </ColWrapper>
  </template>
</template>

<script setup>
import FormValue from './form-value.vue'
import ColWrapper from './col-wrapper.vue'
import { computed, defineModel, useSlots } from 'vue'
import QueryFormItem from '../response-form/query-form-item.vue'
import { ElFormItem } from 'element-plus'
import { dataOmit } from '@/utils/util.js'

const props = defineProps({
  columns: { type: Array, default: () => [] },
  grid: { type: Boolean, default: false },
  isQueryFormItem: { type: Boolean, default: false },
})
const value = defineModel()
const slots = useSlots()

// 表单内容插槽集合
const valueSlots = computed(() => {
  // 排除所有el-form-item的所有的自定义插槽
  const excludedSlots = props.columns.reduce((acc, item) => {
    if (item.slots) {
      for (const slotName in item.slots) {
        if (typeof item.slots[slotName] === 'string') {
          acc.push(item.slots[slotName])
        }
      }
    }
    return acc
  }, [])
  return dataOmit([...excludedSlots, 'default'], slots)
})
</script>

<style scoped lang="scss"></style>
